package com.chen.integral.module.integral.service.impl;

import com.chen.base.module.base.util.StringUtils;
import com.chen.base.module.base.dto.PageResponse;
import com.chen.base.module.base.service.impl.BaseServiceImpl;
import com.chen.dao.integral.IntegralHistoryDao;
import com.chen.entity.integral.IntegralHistory;
import com.chen.integral.module.integral.service.IntegralHistoryService;
import com.chen.integral.module.integral.service.RuleService;
import com.chen.integral.module.integral.vo.IntegerHistoryOneVo;
import com.chen.integral.module.integral.vo.IntegerHistoryQueryVo;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.io.File;
import java.io.FileReader;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Title: manager-spring-mvc-hb
 * @Description: to do
 * @Author: chenjiwei
 * @Date: 2020-11-16 23:28
 * @Version: 1.0.0
 */
@Service
public class IntegralHistoryServiceImpl extends BaseServiceImpl<IntegralHistory> implements IntegralHistoryService<IntegralHistory> {

    @Autowired
    private IntegralHistoryDao integralHistoryDao;

    @Autowired
    private RuleService ruleService;

    @Override
    public JpaSpecificationExecutor getBaseRepository() {
        return integralHistoryDao;
    }

    @Override
    protected String filterForFindAll() {
        return null;
    }

    @Override
    public PageResponse query(IntegerHistoryQueryVo vo) {
        StringBuilder hql = new StringBuilder();
        hql.append(" select integral_id as integralId, ");
        hql.append(" integral_point as integralVal, ");
        hql.append(" integral_desc as integralDesc, ");
        hql.append(" integral_rule as integralRule, ");
        hql.append(" integral_time as integralTime, ");
        hql.append(" integral_user_id as integralUserId ");
        hql.append(" from  t_integral_history ");
        hql.append(" where 1 = 1 ");
        StringBuilder countHql = new StringBuilder();
        countHql.append("select count('*') from t_integral_history where 1 = 1 ");

        StringBuilder where = new StringBuilder();
        Map<String, Object> param = new HashMap<>();
        if(StringUtils.isNotNull(vo.getId())){
            where.append(" and integral_id = :integerId ");
            param.put("integerId", vo.getId());
        }
        if(StringUtils.isNotNull(vo.getId())){
            where.append(" and integral_rule = :rule ");
            param.put("rule", vo.getRule());
        }
        if(StringUtils.isNotNull(vo.getStartTime()) && !StringUtils.isNotNull(vo.getEndTime())){
            where.append(" and integral_time >= :startTime ");
            param.put("startTime", vo.getStartTime());
        }
        if(StringUtils.isNotNull(vo.getEndTime()) && !StringUtils.isNotNull(vo.getStartTime())){
            where.append(" and integral_time <= :endTime ");
            param.put("endTime", vo.getEndTime());
        }
        if(StringUtils.isNotNull(vo.getStartTime()) && StringUtils.isNotNull(vo.getEndTime())){
            where.append(" and integral_time <= :endTime and integral_time >= :startTime ");
            param.put("startTime", vo.getStartTime());
            param.put("endTime", vo.getEndTime());
        }

        hql.append(where).append(" limit ");
        hql.append(vo.getStart()).append(",").append(vo.getSize());
        countHql.append(where);

        return nativeQueryForMap(hql.toString(), countHql.toString(), IntegralHistory.class, param);
    }

    @Override
    public PageResponse queryByIdIn(IntegerHistoryOneVo vo) {
        StringBuilder hql = new StringBuilder();
        hql.append(" select integral_id as integralId, ");
        hql.append(" integral_point as integralVal, ");
        hql.append(" integral_desc as integralDesc, ");
        hql.append(" integral_rule as integralRule, ");
        hql.append(" integral_time as integralTime, ");
        hql.append(" integral_user_id as integralUserId ");
        hql.append(" from  t_integral_history ");
        hql.append(" where 1 = 1 ");
        StringBuilder countHql = new StringBuilder();
        countHql.append("select count('*') from t_integral_history where 1 = 1 ");

        Map<String, Object> param = new HashMap<>();

        StringBuilder where = new StringBuilder();
        where.append(" and integral_id in (:integralId) ");
        param.put("integralId", vo.getIds());

        String query = hql.append(where).toString();
        String countSql = countHql.append(where).toString();

        PageResponse pageResponse = nativeQueryForMap(query, countSql, IntegralHistory.class, param);

        return pageResponse;
    }

    @Override
    public void calcuIntegralByRule(String rule, String user, Date date) throws Exception{
        ScriptObjectMirror func = getScriptObjectMirror(rule, user, date);

        IntegralHistory integralHistory = new IntegralHistory();
        integralHistory.setIntegralRule(rule);
        integralHistory.setIntegralDesc((String) func.getMember("desc"));
        integralHistory.setIntegralTime(new Date());
        integralHistory.setIntegralVal((Integer) func.getMember("point"));
        integralHistory.setIntegralUserId(user);
        integralHistoryDao.save(integralHistory);
    }

    private ScriptObjectMirror getScriptObjectMirror(String rule, String user, Date date) throws Exception {
        ScriptEngineManager engineManager = new ScriptEngineManager();
        ScriptEngine engineByName = engineManager.getEngineByName("nashorn");//只可写JavaScript或javascript
//            ScriptEngine engineByName = engineManager.getEngineByName("JavaScript");//只可写JavaScript或javascript
//        File file = new File("classes/static/js/integral/rule.js");//也可以
        File file = ResourceUtils.getFile("classpath:static/js/integral/rule.js");
        //读取js文件
        FileReader reader = new FileReader(file);
        System.out.println(System.getProperty("user.dir"));
        //执行指定脚本
        engineByName.eval(reader);
        ScriptObjectMirror func = null;
        if (engineByName instanceof Invocable){// object instanceof class ， object 是 class 的一个实例，则 instanceof 运算符返回 true
            // 注入一个全局的变量ruleService
            engineByName.put("ruleService", ruleService);
            Invocable invocable = (Invocable) engineByName;

            //调用merge方法，并传入两个参数
            func = (ScriptObjectMirror) invocable.invokeFunction(rule, user, date);
        }
        reader.close();
        return func;
    }
}
